/// Payments - Create
///
/// **Creates a payment object when amount and currency are passed.**
///
/// This API is also used to create a mandate by passing the `mandate_object`.
///
/// Depending on the user journey you wish to achieve, you may opt to complete all the steps in a single request **by attaching a payment method, setting `confirm=true` and `capture_method = automatic`** in the *Payments/Create API* request.
///
/// Otherwise, To completely process a payment you will have to **create a payment, attach a payment method, confirm and capture funds**. For that you could use the following sequence of API requests -
///
/// 1. Payments - Create
///
/// 2. Payments - Update
///
/// 3. Payments - Confirm
///
/// 4. Payments - Capture.
///
/// You will require the 'API - Key' from the Hyperswitch dashboard to make the first call, and use the 'client secret' returned in this API along with your 'publishable key' to make subsequent API calls from your client.
///
/// This page lists the various combinations in which the Payments - Create API can be used and the details about the various fields in the requests and responses.
#[utoipa::path(
    post,
    path = "/payments",
    request_body(
        content = PaymentsCreateRequest,
        examples(
            (
                "Create a payment with minimal fields" = (
                    value = json!({"amount": 6540,"currency": "USD"})
                )
            ),
            (
                "Create a payment with customer details and metadata" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "payment_id": "abcdefghijklmnopqrstuvwxyz",
                    "customer": {
                      "id": "cus_abcdefgh",
                      "name": "John Dough",
                      "phone": "9123456789",
                      "email": "john@example.com"
                    },
                    "description": "Its my first payment request",
                    "statement_descriptor_name": "joseph",
                    "statement_descriptor_suffix": "JS",
                    "metadata": {
                      "udf1": "some-value",
                      "udf2": "some-value"
                    }
                  })
                )
            ),
            (
                "Create a 3DS payment" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "authentication_type": "three_ds"
                  })
                )
            ),
            (
                "Create a manual capture payment" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "capture_method": "manual"
                  })
                )
            ),
            (
                "Create a setup mandate payment" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "confirm": true,
                    "customer_id": "StripeCustomer123",
                    "authentication_type": "no_three_ds",
                    "payment_method": "card",
                    "payment_method_data": {
                      "card": {
                        "card_number": "4242424242424242",
                        "card_exp_month": "10",
                        "card_exp_year": "25",
                        "card_holder_name": "joseph Doe",
                        "card_cvc": "123"
                      }
                    },
                    "setup_future_usage": "off_session",
                    "mandate_data": {
                      "customer_acceptance": {
                        "acceptance_type": "online",
                        "accepted_at": "1963-05-03T04:07:52.723Z",
                        "online": {
                          "ip_address": "127.0.0.1",
                          "user_agent": "amet irure esse"
                        }
                      },
                      "mandate_type": {
                        "single_use": {
                          "amount": 6540,
                          "currency": "USD"
                        }
                      }
                    },
                    "customer_acceptance": {
                      "acceptance_type": "online",
                      "accepted_at": "1963-05-03T04:07:52.723Z",
                      "online": {
                        "ip_address": "127.0.0.1",
                        "user_agent": "amet irure esse"
                      }
                    }
                  })
                )
            ),
            (
                "Create a recurring payment with mandate_id" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "confirm": true,
                    "customer_id": "StripeCustomer",
                    "authentication_type": "no_three_ds",
                    "mandate_id": "{{mandate_id}}",
                    "off_session": true
                  })
                )
            ),
            (
                "Create a payment and save the card" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "confirm": true,
                    "customer_id": "StripeCustomer123",
                    "authentication_type": "no_three_ds",
                    "payment_method": "card",
                    "payment_method_data": {
                      "card": {
                        "card_number": "4242424242424242",
                        "card_exp_month": "10",
                        "card_exp_year": "25",
                        "card_holder_name": "joseph Doe",
                        "card_cvc": "123"
                      }
                    },
                    "customer_acceptance": {
                      "acceptance_type": "online",
                      "accepted_at": "1963-05-03T04:07:52.723Z",
                      "online": {
                        "ip_address": "127.0.0.1",
                        "user_agent": "amet irure esse"
                      }
                    },
                    "setup_future_usage": "off_session"
                  })
                )
            ),
            (
                "Create a payment using an already saved card's token" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "confirm": true,
                    "client_secret": "{{client_secret}}",
                    "payment_method": "card",
                    "payment_token": "{{payment_token}}",
                    "card_cvc": "123"
                  })
                )
            ),
            (
                "Create a manual capture payment" = (
                    value = json!({
                    "amount": 6540,
                    "currency": "USD",
                    "customer": {
                      "id": "cus_abcdefgh"
                    },
                    "billing": {
                      "address": {
                        "line1": "1467",
                        "line2": "Harrison Street",
                        "line3": "Harrison Street",
                        "city": "San Fransico",
                        "state": "California",
                        "zip": "94122",
                        "country": "US",
                        "first_name": "joseph",
                        "last_name": "Doe"
                      },
                      "phone": {
                        "number": "9123456789",
                        "country_code": "+91"
                      }
                    }
                })
            )
            )
        ),
    ),
    responses(
        (status = 200, description = "Payment created", body = PaymentsCreateResponseOpenApi),
        (status = 400, description = "Missing Mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Create a Payment",
    security(("api_key" = [])),
)]
pub fn payments_create() {}

/// Payments - Retrieve
///
/// Retrieves a Payment. This API can also be used to get the status of a previously initiated payment or next action for an ongoing payment
#[utoipa::path(
    get,
    path = "/payments/{payment_id}",
    params(
        ("payment_id" = String, Path, description = "The identifier for payment")
    ),
    request_body=PaymentRetrieveBody,
    responses(
        (status = 200, description = "Gets the payment with final status", body = PaymentsResponse),
        (status = 404, description = "No payment found")
    ),
    tag = "Payments",
    operation_id = "Retrieve a Payment",
    security(("api_key" = []), ("publishable_key" = []))
)]
pub fn payments_retrieve() {}

/// Payments - Update
///
/// To update the properties of a *PaymentIntent* object. This may include attaching a payment method, or attaching customer object or metadata fields after the Payment is created
#[utoipa::path(
    post,
    path = "/payments/{payment_id}",
    params(
        ("payment_id" = String, Path, description = "The identifier for payment")
    ),
   request_body(
     content = PaymentsUpdateRequest,
     examples(
      (
        "Update the payment amount" = (
          value = json!({
              "amount": 7654,
            }
          )
        )
      ),
      (
        "Update the shipping address" = (
          value = json!(
            {
              "shipping": {
                "address": {
                    "line1": "1467",
                    "line2": "Harrison Street",
                    "line3": "Harrison Street",
                    "city": "San Fransico",
                    "state": "California",
                    "zip": "94122",
                    "country": "US",
                    "first_name": "joseph",
                    "last_name": "Doe"
                },
                "phone": {
                    "number": "9123456789",
                    "country_code": "+91"
                }
              },
            }
          )
        )
      )
     )
    ),
    responses(
        (status = 200, description = "Payment updated", body = PaymentsCreateResponseOpenApi),
        (status = 400, description = "Missing mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Update a Payment",
    security(("api_key" = []), ("publishable_key" = []))
)]
pub fn payments_update() {}

/// Payments - Confirm
///
/// **Use this API to confirm the payment and forward the payment to the payment processor.**
///
/// Alternatively you can confirm the payment within the *Payments/Create* API by setting `confirm=true`. After confirmation, the payment could either:
///
/// 1. fail with `failed` status or
///
/// 2. transition to a `requires_customer_action` status with a `next_action` block or
///
/// 3. succeed with either `succeeded` in case of automatic capture or `requires_capture` in case of manual capture
#[utoipa::path(
    post,
    path = "/payments/{payment_id}/confirm",
    params(
        ("payment_id" = String, Path, description = "The identifier for payment")
    ),
    request_body(
     content = PaymentsConfirmRequest,
     examples(
      (
        "Confirm a payment with payment method data" = (
          value = json!({
              "payment_method": "card",
              "payment_method_type": "credit",
              "payment_method_data": {
                "card": {
                  "card_number": "4242424242424242",
                  "card_exp_month": "10",
                  "card_exp_year": "25",
                  "card_holder_name": "joseph Doe",
                  "card_cvc": "123"
                }
              },
              "customer_acceptance": {
                "acceptance_type": "online",
                "accepted_at": "1963-05-03T04:07:52.723Z",
                "online": {
                  "ip_address": "127.0.0.1",
                  "user_agent": "amet irure esse"
                }
              }
            }
          )
        )
      )
     )
    ),
    responses(
        (status = 200, description = "Payment confirmed", body = PaymentsCreateResponseOpenApi),
        (status = 400, description = "Missing mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Confirm a Payment",
    security(("api_key" = []), ("publishable_key" = []))
)]
pub fn payments_confirm() {}

/// Payments - Capture
///
/// To capture the funds for an uncaptured payment
#[utoipa::path(
    post,
    path = "/payments/{payment_id}/capture",
    params(
        ("payment_id" = String, Path, description = "The identifier for payment")
    ),
    request_body (
        content = PaymentsCaptureRequest,
        examples(
            (
                "Capture the full amount" = (
                    value = json!({})
                )
            ),
            (
                "Capture partial amount" = (
                    value = json!({"amount_to_capture": 654})
                )
            ),
        )
    ),
    responses(
        (status = 200, description = "Payment captured", body = PaymentsResponse),
        (status = 400, description = "Missing mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Capture a Payment",
    security(("api_key" = []))
)]
pub fn payments_capture() {}

#[cfg(feature = "v1")]
/// Payments - Session token
///
/// Creates a session object or a session token for wallets like Apple Pay, Google Pay, etc. These tokens are used by Hyperswitch's SDK to initiate these wallets' SDK.
#[utoipa::path(
  post,
  path = "/payments/session_tokens",
  request_body=PaymentsSessionRequest,
  responses(
      (status = 200, description = "Payment session object created or session token was retrieved from wallets", body = PaymentsSessionResponse),
      (status = 400, description = "Missing mandatory fields")
  ),
  tag = "Payments",
  operation_id = "Create Session tokens for a Payment",
  security(("publishable_key" = []))
)]
pub fn payments_connector_session() {}

#[cfg(feature = "v2")]
/// Payments - Session token
///
/// Creates a session object or a session token for wallets like Apple Pay, Google Pay, etc. These tokens are used by Hyperswitch's SDK to initiate these wallets' SDK.
#[utoipa::path(
    post,
    path = "/v2/payments/{payment_id}/create-external-sdk-tokens",
    request_body=PaymentsSessionRequest,
    responses(
        (status = 200, description = "Payment session object created or session token was retrieved from wallets", body = PaymentsSessionResponse),
        (status = 400, description = "Missing mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Create Session tokens for a Payment",
    security(("publishable_key" = []))
)]
pub fn payments_connector_session() {}

/// Payments - Cancel
///
/// A Payment could can be cancelled when it is in one of these statuses: `requires_payment_method`, `requires_capture`, `requires_confirmation`, `requires_customer_action`.
#[utoipa::path(
    post,
    path = "/payments/{payment_id}/cancel",
    request_body (
        content = PaymentsCancelRequest,
        examples(
            (
                "Cancel the payment with minimal fields" = (
                    value = json!({})
                )
            ),
            (
                "Cancel the payment with cancellation reason" = (
                    value = json!({"cancellation_reason": "requested_by_customer"})
                )
            ),
        )
    ),
    params(
        ("payment_id" = String, Path, description = "The identifier for payment")
    ),
    responses(
        (status = 200, description = "Payment canceled"),
        (status = 400, description = "Missing mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Cancel a Payment",
    security(("api_key" = []))
)]
pub fn payments_cancel() {}

/// Payments - List
///
/// To list the *payments*
#[utoipa::path(
    get,
    path = "/payments/list",
    params(
        ("customer_id" = String, Query, description = "The identifier for the customer"),
        ("starting_after" = String, Query, description = "A cursor for use in pagination, fetch the next list after some object"),
        ("ending_before" = String, Query, description = "A cursor for use in pagination, fetch the previous list before some object"),
        ("limit" = i64, Query, description = "Limit on the number of objects to return"),
        ("created" = PrimitiveDateTime, Query, description = "The time at which payment is created"),
        ("created_lt" = PrimitiveDateTime, Query, description = "Time less than the payment created time"),
        ("created_gt" = PrimitiveDateTime, Query, description = "Time greater than the payment created time"),
        ("created_lte" = PrimitiveDateTime, Query, description = "Time less than or equals to the payment created time"),
        ("created_gte" = PrimitiveDateTime, Query, description = "Time greater than or equals to the payment created time")
    ),
    responses(
        (status = 200, description = "Successfully retrieved a payment list", body = Vec<PaymentListResponse>),
        (status = 404, description = "No payments found")
    ),
    tag = "Payments",
    operation_id = "List all Payments",
    security(("api_key" = []))
)]
pub fn payments_list() {}

/// Profile level Payments - List
///
/// To list the payments
#[utoipa::path(
  get,
  path = "/payments/list",
  params(
      ("customer_id" = String, Query, description = "The identifier for the customer"),
      ("starting_after" = String, Query, description = "A cursor for use in pagination, fetch the next list after some object"),
      ("ending_before" = String, Query, description = "A cursor for use in pagination, fetch the previous list before some object"),
      ("limit" = i64, Query, description = "Limit on the number of objects to return"),
      ("created" = PrimitiveDateTime, Query, description = "The time at which payment is created"),
      ("created_lt" = PrimitiveDateTime, Query, description = "Time less than the payment created time"),
      ("created_gt" = PrimitiveDateTime, Query, description = "Time greater than the payment created time"),
      ("created_lte" = PrimitiveDateTime, Query, description = "Time less than or equals to the payment created time"),
      ("created_gte" = PrimitiveDateTime, Query, description = "Time greater than or equals to the payment created time")
  ),
  responses(
      (status = 200, description = "Received payment list"),
      (status = 404, description = "No payments found")
  ),
  tag = "Payments",
  operation_id = "List all Payments for the Profile",
  security(("api_key" = []))
)]
pub async fn profile_payments_list() {}

/// Payments - Incremental Authorization
///
/// Authorized amount for a payment can be incremented if it is in status: requires_capture
#[utoipa::path(
  post,
  path = "/payments/{payment_id}/incremental_authorization",
  request_body=PaymentsIncrementalAuthorizationRequest,
  params(
      ("payment_id" = String, Path, description = "The identifier for payment")
  ),
  responses(
      (status = 200, description = "Payment authorized amount incremented", body = PaymentsResponse),
      (status = 400, description = "Missing mandatory fields")
  ),
  tag = "Payments",
  operation_id = "Increment authorized amount for a Payment",
  security(("api_key" = []))
)]
pub fn payments_incremental_authorization() {}

/// Payments - External 3DS Authentication
///
/// External 3DS Authentication is performed and returns the AuthenticationResponse
#[utoipa::path(
  post,
  path = "/payments/{payment_id}/3ds/authentication",
  request_body=PaymentsExternalAuthenticationRequest,
  params(
      ("payment_id" = String, Path, description = "The identifier for payment")
  ),
  responses(
      (status = 200, description = "Authentication created", body = PaymentsExternalAuthenticationResponse),
      (status = 400, description = "Missing mandatory fields")
  ),
  tag = "Payments",
  operation_id = "Initiate external authentication for a Payment",
  security(("publishable_key" = []))
)]
pub fn payments_external_authentication() {}

/// Payments - Complete Authorize
///
///
#[utoipa::path(
  post,
  path = "/{payment_id}/complete_authorize",
  request_body=PaymentsCompleteAuthorizeRequest,
  params(
    ("payment_id" =String, Path, description =  "The identifier for payment")
  ),
 responses(
      (status = 200, description = "Payments Complete Authorize Success", body = PaymentsResponse),
      (status = 400, description = "Missing mandatory fields")
  ),
  tag = "Payments",
  operation_id = "Complete Authorize a Payment",
  security(("publishable_key" = []))
)]
pub fn payments_complete_authorize() {}

/// Dynamic Tax Calculation
///
///
#[utoipa::path(
    post,
    path = "/payments/{payment_id}/calculate_tax",
    request_body=PaymentsDynamicTaxCalculationRequest,
    responses(
        (status = 200, description = "Tax Calculation is done", body = PaymentsDynamicTaxCalculationResponse),
        (status = 400, description = "Missing mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Create Tax Calculation for a Payment",
    security(("publishable_key" = []))
)]

pub fn payments_dynamic_tax_calculation() {}

/// Payments - Post Session Tokens
///
///
#[utoipa::path(
    post,
    path = "/payments/{payment_id}/post_session_tokens",
    request_body=PaymentsPostSessionTokensRequest,
    responses(
        (status = 200, description = "Post Session Token is done", body = PaymentsPostSessionTokensResponse),
        (status = 400, description = "Missing mandatory fields")
    ),
    tag = "Payments",
    operation_id = "Create Post Session Tokens for a Payment",
    security(("publishable_key" = []))
)]

pub fn payments_post_session_tokens() {}

/// Payments - Create Intent
///
/// **Creates a payment intent object when amount_details are passed.**
///
/// You will require the 'API - Key' from the Hyperswitch dashboard to make the first call, and use the 'client secret' returned in this API along with your 'publishable key' to make subsequent API calls from your client.
#[utoipa::path(
  post,
  path = "/v2/payments/create-intent",
  request_body(
      content = PaymentsCreateIntentRequest,
      examples(
          (
              "Create a payment intent with minimal fields" = (
                  value = json!({"amount_details": {"order_amount": 6540, "currency": "USD"}})
              )
          ),
      ),
  ),
  responses(
      (status = 200, description = "Payment created", body = PaymentsCreateIntentResponse),
      (status = 400, description = "Missing Mandatory fields")
  ),
  tag = "Payments",
  operation_id = "Create a Payment Intent",
  security(("api_key" = [])),
)]
#[cfg(feature = "v2")]
pub fn payments_create_intent() {}

/// Payments - Confirm Intent
///
/// **Confirms a payment intent object with the payment method data**
///
/// .
#[utoipa::path(
  post,
  path = "/v2/payments/{id}/confirm-intent",
  request_body(
      content = PaymentsConfirmIntentRequest,
      examples(
          (
              "Confirm the payment intent with card details" = (
                  value = json!({
                    "payment_method_type": "card",
                    "payment_method_data": {
                      "card": {
                        "card_number": "4242424242424242",
                        "card_exp_month": "10",
                        "card_exp_year": "25",
                        "card_holder_name": "joseph Doe",
                        "card_cvc": "123"
                      }
                    },
                  })
              )
          ),
      ),
  ),
  responses(
      (status = 200, description = "Payment created", body = PaymentsConfirmIntentResponse),
      (status = 400, description = "Missing Mandatory fields")
  ),
  tag = "Payments",
  operation_id = "Confirm Payment Intent",
  security(("publisable_key" = [])),
)]
#[cfg(feature = "v2")]
pub fn payments_confirm_intent() {}
